const fs = require('fs-extra');
const path = require('path');
const { Controller } = require('egg');
const os = require('os');
const archiver = require('archiver');

class VideoController extends Controller {
  /**
   * 处理MP4视频：提取音频为MP3，创建无音频MP4，并将MP3切割为WAV片段
   */
  async processVideo() {
    const { ctx, app, service } = this;

    try {
      // 使用egg内置的文件上传功能
      const file = await ctx.getFileStream();

      if (!file) {
        ctx.status = 400;
        ctx.body = { success: false, message: '没有找到视频文件' };
        return;
      }

      // 只允许mp4文件
      if (file.mimeType !== 'video/mp4') {
        ctx.status = 400;
        ctx.body = { success: false, message: '只支持MP4格式视频文件' };
        return;
      }

      // 创建临时上传目录
      const uploadDir = path.join(app.baseDir, 'app/public/upload');
      await fs.ensureDir(uploadDir);

      // 生成唯一文件名
      const filename = `${Date.now()}_${Math.floor(Math.random() * 10000)}.mp4`;
      const videoPath = path.join(uploadDir, filename);

      // 创建写入流
      const writeStream = fs.createWriteStream(videoPath);

      // 写入文件
      try {
        await new Promise((resolve, reject) => {
          file.pipe(writeStream);
          file.on('error', reject);
          writeStream.on('finish', resolve);
          writeStream.on('error', reject);
        });
      } catch (err) {
        await fs.unlink(videoPath).catch(() => { });
        ctx.status = 500;
        ctx.body = { success: false, message: '文件上传失败', error: err.message };
        return;
      }

      // 提取音频和创建无声视频
      const { mp3Path, silentVideoPath, outputDir } = await service.video.extractAudioAndCreateSilentVideo(videoPath);

      // 将MP3切割为WAV片段
      const wavSegments = await service.video.splitAudioToWav(mp3Path, 1);

      ctx.body = {
        success: true,
        data: {
          mp3: `/public/output/${path.basename(outputDir)}/${path.basename(mp3Path)}`,
          silentVideo: `/public/output/${path.basename(outputDir)}/${path.basename(silentVideoPath)}`,
          wavSegments: wavSegments.map(segment => {
            return `/public/output/${path.basename(outputDir)}/wav_segments/${path.basename(segment)}`;
          }),
        },
      };

      // 删除原始上传文件以节省空间
      try {
        await fs.unlink(videoPath);
      } catch (e) {
        console.error('清理上传文件失败:', e);
      }
    } catch (error) {
      console.error('处理视频时发生错误:', error);
      ctx.status = 500;
      ctx.body = { success: false, message: '处理视频时发生错误', error: error.message };
    }
  }

  /**
   * 生成指定数量的随机网页特效
   */
  async generateWebEffects() {
    const { ctx, service } = this;

    try {
      const { count = 1 } = ctx.query;

      // 验证count参数
      const effectCount = parseInt(count, 10);
      if (isNaN(effectCount) || effectCount < 1 || effectCount > 20) {
        ctx.status = 400;
        ctx.body = { success: false, message: '无效的count参数，必须为1-20之间的整数' };
        return;
      }

      const effects = await service.video.generateWebEffects(effectCount);

      ctx.body = {
        success: true,
        data: {
          count: effects.length,
          effects: effects.map(effect => ({
            id: effect.id,
            url: effect.url,
            opacity: effect.opacity,
            type: effect.type
          }))
        }
      };
    } catch (error) {
      console.error('生成网页特效时发生错误:', error);
      ctx.status = 500;
      ctx.body = { success: false, message: '生成网页特效时发生错误', error: error.message };
    }
  }

  /**
   * 生成指定数量的随机视频特效
   */
  async generateVideoEffects() {
    const { ctx, service } = this;

    try {
      const { count = 1 } = ctx.query;

      // 验证count参数
      const effectCount = parseInt(count, 10);
      if (isNaN(effectCount) || effectCount < 1 || effectCount > 10) {
        ctx.status = 400;
        ctx.body = { success: false, message: '无效的count参数，必须为1-10之间的整数' };
        return;
      }

      const effects = await service.video.generateVideoEffects(effectCount);

      ctx.body = {
        success: true,
        data: {
          count: effects.length,
          effects: effects.map(effect => ({
            id: effect.id,
            url: effect.url,
            opacity: effect.opacity,
            type: effect.type
          }))
        }
      };
    } catch (error) {
      console.error('生成视频特效时发生错误:', error);
      ctx.status = 500;
      ctx.body = { success: false, message: '生成视频特效时发生错误', error: error.message };
    }
  }

  /**
   * 批量下载特效文件，打包成ZIP
   */
  async downloadEffectsAsZip() {
    const { ctx, app } = this;

    try {
      const { urls, type } = ctx.request.body;

      if (!urls || !Array.isArray(urls) || urls.length === 0) {
        ctx.status = 400;
        ctx.body = { success: false, message: '未提供有效的文件URL列表' };
        return;
      }

      // 确定类型并设置合适的ZIP文件名
      const zipFileName = `${type || 'effects'}_${Date.now()}.zip`;
      const zipFilePath = path.join(app.baseDir, 'app/public/download', zipFileName);

      // 确保下载目录存在
      await fs.ensureDir(path.dirname(zipFilePath));

      // 创建写入流
      const output = fs.createWriteStream(zipFilePath);
      const archive = archiver('zip', {
        zlib: { level: 9 } // 设置压缩级别
      });

      // 监听关闭事件
      output.on('close', () => {
        console.log(`ZIP archive created: ${archive.pointer()} total bytes`);
      });

      // 监听错误事件
      archive.on('error', (err) => {
        throw err;
      });

      // 将输出流与archive关联
      archive.pipe(output);

      // 添加文件到ZIP
      for (const url of urls) {
        if (!url) continue;

        // 从URL中提取实际文件路径
        const filePath = path.join(app.baseDir, 'app/public', url.replace(/^\/public\//, ''));

        if (await fs.pathExists(filePath)) {
          // 为了在ZIP中保持良好的目录结构
          const filename = path.basename(filePath);
          archive.file(filePath, { name: filename });
        }
      }

      // 完成归档
      await archive.finalize();

      // 响应下载链接
      ctx.body = {
        success: true,
        data: {
          downloadUrl: `/public/download/${zipFileName}`
        }
      };
    } catch (error) {
      console.error('打包ZIP文件时发生错误:', error);
      ctx.status = 500;
      ctx.body = { success: false, message: '打包ZIP文件时发生错误', error: error.message };
    }
  }
}

module.exports = VideoController; 